package com.zxl.jdk8test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 函数式回调测试
 * 用于解决异步调用和回调地狱问题
 * @author zxl
 *
 */
public class CompletableFutureTest {
    
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // CompletableFuture 表示一个异步计算的结果，支持在计算完成后触发回调或组合多个异步操作。
        // 异步计算的结果可以通过 thenApply 方法进行转换，
        // 也可以通过 thenAccept 方法进行消费，
        // 还可以通过 thenRun 方法执行一些额外的操作。
        // runAsync 方法用于执行一个无返回值的异步操作。
        // supplyAsync 有返回值的异步任务（使用 ForkJoinPool 线程池）
        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(1500);
            } catch (Exception e) {
                e.printStackTrace();
            }return "12";});
        CompletableFuture<Integer> futureInt = supplyAsync.thenApply(Integer::parseInt);
        CompletableFuture<Double> futureDouble = supplyAsync.thenApply(Double::parseDouble);
        // 该句执行与否不影响后面两句，包括线程休眠
        // 非阻塞获取结果（若未完成则返回默认值）
        System.out.println(supplyAsync.getNow("ad"));//ad 不等待线程执行完的返回
        //后面两个不会线程休眠，只有第一个会。当第一个执行完后面两个立即执行。
        // get阻塞获取结果（超时则抛异常）
        // join 阻塞获取结果（完成或异常时触发）
        System.out.println(futureInt.get() + " int");//12
        System.out.println(futureDouble.get());//12.0

        // 尝试完成（若未完成则设置值，已完成则返回 false）
//        boolean completed = supplyAsync.complete("Manual Result");

        // 异常完成
//        supplyAsync.completeExceptionally(new RuntimeException("Error"));

        // 链式调用
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
                .thenApply(s -> s + " World")
                .thenApply(String::toUpperCase);

        // 结果：HELLO WORLD

        // 有输入，无返回值
        CompletableFuture<Void> acceptFuture = CompletableFuture.supplyAsync(() -> "Result")
                .thenAccept(result -> System.out.println("Consumed: " + result));

        // 无输入，无返回值
        CompletableFuture<Void> runFuture = CompletableFuture.supplyAsync(() -> "Result")
                .thenRun(() -> System.out.println("Task completed"));

        // thenCompose：连接两个 CompletableFuture
        CompletableFuture<String> composeFuture = CompletableFuture.supplyAsync(() -> "Hello")
                .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));

        // thenCombine：合并两个独立的 CompletableFuture
        CompletableFuture<Integer> combineFuture = CompletableFuture.supplyAsync(() -> 2)
                .thenCombine(CompletableFuture.supplyAsync(() -> 3), (a, b) -> a * b);
        // 结果：6
    }
}
